package com.dlc.shop.api.controller;


import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.huifu.bspay.sdk.opps.core.request.V2TradePaymentJspayRequest;
import com.huifu.bspay.sdk.opps.core.request.V2TradePaymentScanpayRefundRequest;
import com.huifu.bspay.sdk.opps.core.utils.DateTools;
import com.huifu.bspay.sdk.opps.core.utils.SequenceTools;
import com.dlc.shop.api.huifu.OppsMerchantConfigDemo;
import com.dlc.shop.bean.dto.allinpay.HuiFuDTO;
import com.dlc.shop.bean.model.*;
import com.dlc.shop.common.enums.PayType;
import com.dlc.shop.common.response.ResponseEnum;
import com.dlc.shop.common.response.ServerResponseEntity;
import com.dlc.shop.common.util.ExceptionUtils;
import com.dlc.shop.service.*;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.servlet.http.HttpServletRequest;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.security.KeyFactory;
import java.security.PrivateKey;
import java.security.Signature;
import java.security.spec.PKCS8EncodedKeySpec;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.*;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import static com.dlc.shop.api.huifu.BaseCommonDemo.doExecute;
import static com.dlc.shop.api.huifu.BaseCommonDemo.doInit;

/**
 * @author gaozijie
 * @date 2023-03-28
 */
@Slf4j
@Tag(name = "汇付支付")
@RestController
@RequestMapping("/huifu")
@AllArgsConstructor
public class HuifuController {

    private final OrderService orderService;

    private final HuifuService huifuService;

    private final SkuService skuService;

    private final OrderItemService orderItemService;

    private final ShopDetailService shopDetailService;


    @GetMapping("/getHuiFuQrCode")
    @Operation(summary = "获取汇付二维码")
    public ServerResponseEntity<String> getHuiFuQrCode(HuiFuDTO huiFuDTO) throws Exception {

        Huifu huifu = huifuService.getOne(new LambdaQueryWrapper<Huifu>()
                .eq(Huifu::getOrderNumber, huiFuDTO.getOrderNumber()));
        if(huifu != null){
            if(huifu.getAsynStat().equals("S")){
                return ServerResponseEntity.fail(ResponseEnum.SHOW_FAIL,"该订单已付款,请勿重复付款");
            }else {
                if(huifu.getTradeType().equals(huiFuDTO.getTradeType())){
                    return ServerResponseEntity.success(huifu.getQrCode());
                }
            }
        }else {
            huifu = new Huifu();
        }


        // 1. 数据初始化
        doInit(OppsMerchantConfigDemo.getMerchantConfig());

        Order order = orderService.getOrderByOrderNumber(huiFuDTO.getOrderNumber());

        // 2.组装请求参数
        V2TradePaymentJspayRequest request = new V2TradePaymentJspayRequest();
        // 请求日期
        request.setReqDate(DateTools.getCurrentDateYYYYMMDD());
        // 请求流水号
        request.setReqSeqId(SequenceTools.getReqSeqId32());
        // 商户号
        request.setHuifuId("6666000152203117");
        // 商品描述
        request.setGoodsDesc(order.getProdName());
        // 交易类型
        request.setTradeType(huiFuDTO.getTradeType());
        // 交易金额
        request.setTransAmt(String.format("%.2f", order.getActualTotal()));

        // 设置非必填字段
        Map<String, Object> extendInfoMap = getExtendInfos(order);
        request.setExtendInfo(extendInfoMap);

        // 3. 发起API调用
        Map<String, Object> response = doExecute(request);
        log.info("返回数据:" + JSONObject.toJSONString(response));

        ExecutorService executorService = Executors.newFixedThreadPool(3);
        Huifu finalHuifu = huifu;
        executorService.execute(() -> {
            try {
                Thread.currentThread().setName("getHuiFuQrCode-Thread-"+Thread.currentThread().getId());
                finalHuifu.setTransStat(response.get("trans_stat").toString());
                finalHuifu.setReqSeqId(request.getReqSeqId());
                finalHuifu.setReqDate(request.getReqDate());
                finalHuifu.setGoodsDesc(request.getGoodsDesc());
                finalHuifu.setTradeType(request.getTradeType());
                finalHuifu.setTransAmt(request.getTransAmt());
                finalHuifu.setReqParam(JSONObject.toJSONString(request));
                finalHuifu.setRespParam(response.toString());
                finalHuifu.setCreateTime(new Date());
                finalHuifu.setOrderId(order.getOrderId());
                finalHuifu.setOrderNumber(order.getOrderNumber());
                finalHuifu.setQrCode(response.get("qr_code").toString());
                finalHuifu.setOverdue(extendInfoMap.get("time_expire").toString());
                if(finalHuifu.getId() != null){
                    huifuService.updateById(finalHuifu);
                    log.info("=================================走了更新");
                }else {
                    log.info("=================================走了新增");
                    huifuService.save(finalHuifu);
                }

            } catch (Exception e) {
                log.info("汇付信息保存失败:"+ ExceptionUtils.getRunException(e));
            }finally {
                executorService.shutdown();
            }
        });


        if(!response.get("trans_stat").equals("F")){
            return ServerResponseEntity.success(response.get("qr_code").toString());
        }else {
            return ServerResponseEntity.fail(ResponseEnum.SHOW_FAIL,response.get("resp_desc").toString());
        }

    }


    @PostMapping("/huiFuCallback")
    @Operation(summary = "汇付回调")
    public void huiFuCallback(HttpServletRequest request) throws ParseException {
        log.info("回调数据:request.getParameter(resp_code)========================================================" + request.getParameter("resp_code"));
        log.info("回调数据:request.getParameter(resp_desc)========================================================" + request.getParameter("resp_desc"));
        log.info("回调数据:request.getParameter(sign)========================================================" + request.getParameter("sign"));
        log.info("回调数据:request.getParameter(resp_data)======================================================" + request.getParameter("resp_data"));
        JSONObject respData = JSONObject.parseObject(request.getParameter("resp_data"));

//        huifuService.huiFuCallback(request);
//        JSONObject respData = JSONObject.parseObject(request.getParameter("resp_data"));


//        boolean sign = RsaUtils.verify(request.getParameter("resp_data"), Base64.getEncoder().encodeToString(DemoTestConstants.DEMO_RSA_PUBLIC_KEY.getBytes(StandardCharsets.UTF_8)), request.getParameter("sign"));
//        if(!sign){
//            throw new RuntimeException("签名验证失败");
//        }

//        boolean sign = RsaUtils.verify(request.getParameter("resp_data"), DemoTestConstants.DEMO_RSA_PUBLIC_KEY, request.getParameter("sign"));
//        log.info("签名验证结果:==========================================================="+sign);
//        if(!sign){
//            throw new RuntimeException("签名验证失败");
//        }

        Huifu huifu = huifuService.getOne(new LambdaQueryWrapper<Huifu>()
                .eq(Huifu::getReqSeqId, respData.get("req_seq_id").toString()));
        if(huifu != null && huifu.getAsynStat().equals("S")){
            return;
        }

        String respCode = request.getParameter("resp_code");

        if(huifu != null){
            huifu.setAsynStat(respData.get("trans_stat").toString());
            huifu.setAsynRespParam(respData.toString());
            huifuService.updateById(huifu);
        }else {
            throw new RuntimeException("汇付信息不存在");
        }

        if(respCode.equals("00000000") && respData.get("trans_stat").equals("S")){
            Order order = orderService.getById(huifu.getOrderId());
            if(huifu.getTradeType().equals("A_NATIVE")){
                order.setPayType(PayType.ALIPAY.value());
            }else if(huifu.getTradeType().equals("T_NATIVE")){
                order.setPayType(PayType.WECHATPAY_SWEEP_CODE.value());
            } else if (huifu.getTradeType().equals("U_NATIVE")) {
                order.setPayType(PayType.UNION_PAY.value());
            }
            order.setStatus(2);
            SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");
            order.setPayTime(sdf.parse(respData.get("end_time").toString()));
            order.setIsPayed(1);
            orderService.updateById(order);
        }
        log.info("方法结束==================================================");
    }


    @GetMapping("/refund")
    @Operation(summary = "退款")
    public void huiFuRefund(HuiFuDTO huiFuDTO) throws Exception {
        // 1. 数据初始化
        doInit(OppsMerchantConfigDemo.getMerchantConfig());

        // 2.组装请求参数
        V2TradePaymentScanpayRefundRequest request = new V2TradePaymentScanpayRefundRequest();
        // 请求日期
        request.setReqDate(DateTools.getCurrentDateYYYYMMDD());
        Huifu huifu = huifuService.getOne(new LambdaQueryWrapper<Huifu>()
                .eq(Huifu::getOrderNumber, huiFuDTO.getOrderNumber()));
        // 请求流水号
        request.setReqSeqId(huifu.getReqSeqId());
        // 商户号
        request.setHuifuId("6666000152203117");
        // 申请退款金额
        request.setOrdAmt(huifu.getTransAmt());
        // 原交易请求日期
        request.setOrgReqDate(huifu.getReqDate());

        // 设置非必填字段
        Map<String, Object> extendInfoMap = getRefundExtendInfos();
        request.setExtendInfo(extendInfoMap);

        // 3. 发起API调用
        Map<String, Object> response = doExecute(request);
        log.info("返回数据:" + JSONObject.toJSONString(response));
    }

    private  Map<String, Object> getExtendInfos(Order order) throws ParseException {
        // 设置非必填字段
        Map<String, Object> extendInfoMap = new HashMap<>();
        // 账户号
        // extendInfoMap.put("acct_id", "");
        // 交易有效期
        LocalDateTime localDateTime = LocalDateTime.now().plusMinutes(30);
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");
        Date date = Date.from(localDateTime.atZone(ZoneId.systemDefault()).toInstant());
        String format = sdf.format(date);
        extendInfoMap.put("time_expire", format);
//        // 微信参数集合
//        // extendInfoMap.put("wx_data", getWxData());
//        // 支付宝参数集合
//        extendInfoMap.put("alipay_data", getAlipayData());
//        // 银联参数集合
//        // extendInfoMap.put("unionpay_data", getUnionpayData());
//        // 是否延迟交易
        extendInfoMap.put("delay_acct_flag", "Y");
//        // 手续费扣款标志
//        // extendInfoMap.put("fee_flag", "");
//        // 分账对象
        extendInfoMap.put("acct_split_bunch", getAcctSplitBunch(order));
//        // 传入分账遇到优惠的处理规则
//        extendInfoMap.put("term_div_coupon_type", "0");
//        // 补贴支付信息
//        // extendInfoMap.put("combinedpay_data", getCombinedpayData());
//        // 禁用信用卡标记
//        extendInfoMap.put("limit_pay_type", "NO_CREDIT");
//        // 商户贴息标记
//        extendInfoMap.put("fq_mer_discount_flag", "N");
//        // 渠道号
//        extendInfoMap.put("channel_no", "");
//        // 场景类型
//        extendInfoMap.put("pay_scene", "02");
//        // 备注
//        extendInfoMap.put("remark", "String");
        // 安全信息
//        extendInfoMap.put("risk_check_data", getRiskCheckData());
        // 设备信息
//        extendInfoMap.put("terminal_device_data", getTerminalDeviceData());
        // 异步通知地址
        extendInfoMap.put("notify_url", "http://y7m9vf.natappfree.cc/huifu/huiFuCallback");
        return extendInfoMap;
    }


    private  String getAcctSplitBunch(Order order) {
        JSONObject dto = new JSONObject();
        // 分账明细
         dto.put("acct_infos", getAcctInfosRucan(order));

        return dto.toJSONString();
    }
    private  JSON getAcctInfosRucan(Order order) {
        JSONObject dto = new JSONObject();
        // 分账金额
        // dto.put("div_amt", "test");
        // 分账接收方ID
        // dto.put("huifu_id", "test");
        // 账户号
        // dto.put("acct_id", "");
        double aDouble = 0d;
        List<OrderItem> orderItems = orderItemService.getOrderItemsByOrderNumber(order.getOrderNumber(), false);
        for (OrderItem orderItem : orderItems) {
            Sku sku = skuService.getSkuBySkuId(orderItem.getSkuId());
            aDouble+=sku.getSupplierPrice();
        }
        ShopDetail shopDetail = shopDetailService.getById(order.getShopId());
        // 分账金额
         dto.put("div_amt", aDouble);
        // 分账接收方ID
         dto.put("huifu_id", shopDetail.getHuifuId());

        JSONArray dtoList = new JSONArray();
        dtoList.add(dto);

        JSONObject dto1 = new JSONObject();
        dto1.put("div_amt", order.getActualTotal()-aDouble);
        // 分账接收方ID
        dto1.put("huifu_id", "6666000152203117");
        return dtoList;
    }



    /**
     * 非必填字段
     * @return
     */
    private static Map<String, Object> getRefundExtendInfos() {
        // 设置非必填字段
        Map<String, Object> extendInfoMap = new HashMap<>();
        // 原交易全局流水号
        extendInfoMap.put("org_hf_seq_id", "002900TOP3B221107142320P992ac139c0c00000");
        // 原交易微信支付宝的商户单号
        // extendInfoMap.put("org_party_order_id", "");
        // 原交易请求流水号
        // extendInfoMap.put("org_req_seq_id", "");
        // 分账对象
        // extendInfoMap.put("acct_split_bunch", getAcctSplitBunchRucan());
        // 聚合正扫微信拓展参数集合
        // extendInfoMap.put("wx_data", getWxData());
        // 数字货币扩展参数集合
        // extendInfoMap.put("digital_currency_data", getDigitalCurrencyData());
        // 补贴支付信息
        // extendInfoMap.put("combinedpay_data", getCombinedpayData());
        // 备注
        // extendInfoMap.put("remark", "");
        // 是否垫资退款
        // extendInfoMap.put("loan_flag", "");
        // 垫资承担者
        // extendInfoMap.put("loan_undertaker", "");
        // 垫资账户类型
        // extendInfoMap.put("loan_acct_type", "");
        // 安全信息
        // extendInfoMap.put("risk_check_data", getRiskCheckData());
        // 设备信息
        // extendInfoMap.put("terminal_device_data", getTerminalDeviceData());
        // 异步通知地址
        // extendInfoMap.put("notify_url", "");
        // 银联参数集合
        // extendInfoMap.put("unionpay_data", getUnionpayData());
        return extendInfoMap;
    }











    public static void main(String[] args) {
        LocalDateTime localDateTime = LocalDateTime.now().plusMinutes(30);
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");
        Date date = Date.from(localDateTime.atZone(ZoneId.systemDefault()).toInstant());
        String format = sdf.format(date);
        log.info(format);


    }





















    /**
     * RSA私钥签名：签名方式SHA256WithRSA
     * @param data 待签名字符串
     * @param privateKeyBase64 私钥（Base64编码）
     * @return 签名byte[]
     * @throws Exception
     */
    public static String sign(String data, String privateKeyBase64) {
        // Base64 --> Key
        try {
            byte[] bytes = Base64.getDecoder().decode(privateKeyBase64);
            PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(bytes);
            KeyFactory keyFactory;
            keyFactory = KeyFactory.getInstance("RSA");
            PrivateKey privateKey = keyFactory.generatePrivate(keySpec);
            // Sign
            Signature signature = Signature.getInstance("SHA256WithRSA");
            signature.initSign(privateKey);
            signature.update(data.getBytes("UTF-8"));
            return Base64.getEncoder().encodeToString(signature.sign());
        } catch (Exception e) {
           log.info( ExceptionUtils.getRunException(e));
            return null;
        }
    }
    /**
     * 使用汇付RSA公钥验签
     * @param data 待签名字符串
     * @param publicKeyBase64 公钥（Base64编码）
     * @return 验签结果
     * @throws Exception
     */
//    public static boolean verify(String data, String publicKeyBase64, String sign) {
//        // Base64 --> Key
//        try {
//            byte[] bytes = Base64.getDecoder().decode(publicKeyBase64);
//            X509EncodedKeySpec keySpec = new X509EncodedKeySpec(bytes);
//            KeyFactory keyFactory;
//            keyFactory = KeyFactory.getInstance("RSA");
//            PublicKey publicKey = keyFactory.generatePublic(keySpec);
//            // verify
//            Signature signature = Signature.getInstance("SHA256WithRSA");
//            signature.initVerify(publicKey);
//            signature.update(data.getBytes("UTF-8"));
//            return signature.verify(Base64.getDecoder().decode(sign));
//        } catch (Exception e) {
//            return false;
//        }
//
//    }
}
